﻿using System;
using System.Collections.Generic;

namespace ComputationalGeometry.Shapes
{
    public class Polygon
    {
        readonly List<Point2D> _vertices;

        public Polygon()
        {
            _vertices = new List<Point2D>();
        }

        public Polygon(List<Point2D> initialVertices)
        {
            _vertices = initialVertices;
        }

        public int Size
        {
            get
            {
                return _vertices.Count;
            }
        }

        public void AddPoint(Point2D point)
        {
            if (point == null) 
                throw new ArgumentNullException("point");

            _vertices.Add(point);
            SortByX();
        }

        public void AddPoints(IEnumerable<Point2D> points)
        {
            if (points == null)
                throw new ArgumentNullException("points");

            _vertices.AddRange(points);
            SortByX();
        }

        public double Area()
        {
            double area = 0;

            for (int i = 0; i < _vertices.Count; i++)
            {
                int j = (i + 1) % _vertices.Count;
                area += _vertices[i].X * _vertices[j].Y;
                area -= _vertices[i].Y * _vertices[j].X;
            }

            return area /= 2;

            ////return (area < 0 ? -area : area);
        }

        public Point2D Centroid()
        {
            double cx = 0;
            double cy = 0;
            double area = Area();

            for (int i = 0; i < _vertices.Count; i++)
            {
                int j = (i + 1) % _vertices.Count;

                double factor = _vertices[i].X * _vertices[j].Y -
                                _vertices[i].Y * _vertices[j].X;

                cx += (_vertices[i].X + _vertices[j].X) * factor;
                cy += (_vertices[i].Y + _vertices[j].Y) * factor;
            }

            cx = cx / (6 * area);
            cy = cy / (6 * area);

            return new Point2D(cx, cy);
        }

        private void SortByX()
        {
            Point2DComparer vComparer = new Point2DComparer {ComparisonType = PointComparisonType.CompareX};

            _vertices.Sort(vComparer.Compare);
        }
    }
}
